<?php
/**
 * Created by PhpStorm.
 * User: hui
 * Date: 16/7/22
 * Time: 22:08
 */
namespace app\index\model;

use think\Cookie;
use think\Model;
use think\Db;
use my\Security;
use think\Session;

/**
 * Class Auth 验证模块
 * @package app\index\model
 */
class Auth extends Model
{
    /**
     * 设置加密密钥
     * @var string
     */
    private static $apikey = 'ac74897169ff713953040c0f795911c6';

    /**
     * 获取加密密钥
     * @return string
     */
    public static function get_api_key()
    {
        return self::$apikey;
    }

    /**
     * 首次登录检查
     * @param array $data
     * @return array
     */
    public function login_check($data)
    {
        $apikey = self::$apikey;
        $data['password'] = strtoupper(md5($data['password']));
        //对比验证码
        if (!captcha_check($data['captcha'], $data['id'])) {
            return ['status' => 4]; //验证码错误返回4
        }
        //与数据库核对
        if ($user = Db::table('u_card')
            ->alias('c')
            ->join('u_member m', 'c.ID = m.CardID')
            ->field('c.Card,c.Password,m.Member,m.ID')
            ->where('c.Card', $data['username'])
            ->find()
        ) {
            if ($user['Password'] == $data['password']) {
                $time = time();
                $info = $this->ip_info();
                if (isset($info[0])) {
                    unset($info[0]);
                    $info['ip'] = $this->get_real_ip();
                    $info['country'] = '未知的国家';
                    $info['province'] = '未知的省份';
                    $info['city'] = '未知的城市';
                    $info['district'] = '未知的行政区';
                    $info['carrier'] = '未知的运营商';
                }
                $info['uuid'] = $user['ID'];
                $info['uid'] = Security::encrypt($user['ID'], $apikey);
                $info['token'] = Security::encrypt($time . $user['Card'], $apikey);
                $info['browser'] = $this->get_browser();
                $info['os'] = $this->get_os();
                $info['time'] = $time;
                $name = Security::encrypt($user['Member'], $apikey);
                //检查是否勾选记住登录
                if ($data['remember'] === 'true') {
                    //设置cookie
                    Cookie::set('auth', ['uid' => $info['uid'], 'token' => $info['token'], 'name' => $name], 604800);
                }
                $session = ['uid' => $info['uid'], 'token' => $info['token'], 'name' => $name];
                $this->set_login_session($session);
                $this->save_login_info($info);
                return ['status' => 1]; //密码正确返回1
            } else {
                return ['status' => 2]; //密码错误返回2
            }
        } else {
            return ['status' => 3]; //卡号错误返回3
        }
    }

    /**
     * 设置登录Session
     * @param array $session
     */
    public function set_login_session($session = '')
    {
        $data = $session != '' ? $session : Cookie::get('auth');
        $res = $this->get_en_de($data, 'de');
        if (isset($data['uid'])) {
            Session::set('uuid', $res['uid']);
            Session::set('name', $res['name']);
        }
        Session::set('last_access', time());
    }

    /**
     * 批量加密解密
     * @param array  $data
     * @param string $type
     * @return mixed
     */
    private function en_de($data, $type)
    {
        foreach ($data as $key => $value) {
            if ($type == 'en') {
                $res[$key] = Security::encrypt($value, self::$apikey);
            } elseif ($type == 'de') {
                $res[$key] = Security::decrypt($value, self::$apikey);
            }
        }
        return $res;
    }

    /**
     * 判断加密解密参数正确
     * @param array  $data
     * @param string $type
     * @return bool|mixed
     */
    public function get_en_de($data, $type = 'en')
    {
        if (is_array($data)) {
            foreach ($data as $value) {
                if (!is_array($value) && ($type == 'en' || $type == 'de')) {
                    return $this->en_de($data, $type);
                } else {
                    return false;
                }
            }
        }
        return false;
    }

    /**
     * 保存登录信息到数据库
     * @param array $info
     */
    private function save_login_info($info)
    {
        $login = new LoginLog();
        $login->save($info);
    }

    /**
     * 查看是否登录
     * @return bool
     */
    public function login_status()
    {
        if ((Session::has('uuid') && (time() - Session::get('last_access')) < 600) || $this->check_cookie()) {
            $this->set_login_session();
            return true;
        } else {
            Session::clear();
            return false;
        }
    }

    /**
     * 检查cookie有效期
     * @return array|bool|false|\PDOStatement|string|Model
     */
    public function check_cookie()
    {
        if (Cookie::has('auth')) {
            $uid = Cookie::get('auth')['uid'];
            $token = Cookie::get('auth')['token'];
            $time = time() - 604800;
            $loginLog = LoginLog::where('token', $token)
                ->where('uid', $uid)
                ->where('time', '>', $time)
                ->find();
            return $loginLog;
        } else {
            return false;
        }
    }

    /**
     * 获取用户真实IP
     * @return null|string
     */
    public function get_real_ip()
    {
        static $realIp = null;
        if ($realIp !== null) {
            return $realIp;
        }
        if (isset($_SERVER)) {
            if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
                /* 取X-Forwarded-For中第一个非unknown的有效IP字符串 */
                foreach ($arr AS $ip) {
                    $ip = trim($ip);
                    if ($ip != 'unknown') {
                        $realIp = $ip;
                        break;
                    }
                }
            } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
                $realIp = $_SERVER['HTTP_CLIENT_IP'];
            } else {
                if (isset($_SERVER['REMOTE_ADDR'])) {
                    $realIp = $_SERVER['REMOTE_ADDR'];
                } else {
                    $realIp = '0.0.0.0';
                }
            }
        } else {
            if (getenv('HTTP_X_FORWARDED_FOR')) {
                $realIp = getenv('HTTP_X_FORWARDED_FOR');
            } elseif (getenv('HTTP_CLIENT_IP')) {
                $realIp = getenv('HTTP_CLIENT_IP');
            } else {
                $realIp = getenv('REMOTE_ADDR');
            }
        }
        preg_match("/[\d\.]{7,15}/", $realIp, $onlineIp);
        $realIp = !empty($onlineIp[0]) ? $onlineIp[0] : '0.0.0.0';
        return $realIp;
    }

    /**
     * 获取IP信息
     * @return mixed
     */
    public function ip_info()
    {
        $ip = $this->get_real_ip();
        $ch = curl_init();
        //$url = 'http://apis.baidu.com/apistore/iplookupservice/iplookup?ip=' . $ip;
        $url = 'http://ip.taobao.com/service/getIpInfo.php?ip=' . $ip;

        $header = [
            'apikey: ' . self::$apikey,
        ];
        // 添加apiKey到header
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        // 执行HTTP请求
        curl_setopt($ch, CURLOPT_URL, $url);
        $ipInfo = curl_exec($ch);
        $ipInfo = json_decode($ipInfo, true);
        for ($i = 0; $i < 5; $i++) {
            if ($ipInfo['errNum'] == 1) {
                $ipInfo = curl_exec($ch);
                $ipInfo = json_decode($ipInfo, true);
            } else {
                break;
            }
        }
        $data = [
            'country' => $ipInfo['data']['country'],
            'province' => $ipInfo['data']['region'],
            'city' => $ipInfo['data']['city'],
            'district' => $ipInfo['data']['area'],
            'carrier' => $ipInfo['data']['isp'],
            'ip' => $ipInfo['data']['ip']
        ];
        return $data;
    }

    /**
     * 获取用户浏览器内核
     * @return bool|string
     */
    public function get_browser()
    {
        if (!empty($_SERVER['HTTP_USER_AGENT'])) {
            $br = $_SERVER['HTTP_USER_AGENT'];
            if (preg_match('/MSIE/i', $br)) {
                $br = 'MSIE';
            } elseif (preg_match('/Firefox/i', $br)) {
                $br = 'Firefox';
            } elseif (preg_match('/Chrome/i', $br)) {
                $br = 'Chrome';
            } elseif (preg_match('/Safari/i', $br)) {
                $br = 'Safari';
            } elseif (preg_match('/Opera/i', $br)) {
                $br = 'Opera';
            } else {
                $br = 'Other';
            }
            return $br;
        } else {
            return false;
        }
    }

    /**
     * 获取用户操作系统
     * @return bool|string
     */
    public function get_os()
    {
        if (!empty($_SERVER['HTTP_USER_AGENT'])) {
            $OS = $_SERVER['HTTP_USER_AGENT'];
            if (preg_match('/win/i', $OS)) {
                $OS = 'Windows';
            } elseif (preg_match('/mac/i', $OS)) {
                $OS = 'MAC';
            } elseif (preg_match('/linux/i', $OS)) {
                $OS = 'Linux';
            } elseif (preg_match('/unix/i', $OS)) {
                $OS = 'Unix';
            } elseif (preg_match('/bsd/i', $OS)) {
                $OS = 'BSD';
            } else {
                $OS = 'Other';
            }
            return $OS;
        } else {
            return false;
        }
    }

    /**
     * 清除登录信息
     */
    public function clear()
    {
        Cookie::clear('auth');
        Session::clear();
    }
}
